using System;
using System.IO;
using System.Collections;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace iPodShuffle
{
	public class iPodShuffleHelper
	{
		// returns drives 'CDEF' where ipod shuffle folder is found
		static public string LocateDrives()
		{
			string[] drives = Directory.GetLogicalDrives();

			string ipod = string.Empty;
			foreach (string drive in drives)
			{
				char dr = drive[0];

				if ( dr != 'A' && dr != 'B' )
				{
					string folder = Path.Combine( drive, @"iPod_Control\iTunes" );
					if (Directory.Exists( folder ))
						ipod += dr;
				}
			}

			return ipod;
		}

		static public string[] GetSoundFiles( char drive )
		{
			string folder = drive+@":\";

			ArrayList list = GetSoundFilesFromDir( folder );

			string[] sort = (string[]) list.ToArray( typeof(string) );
			Array.Sort( sort );
			return sort;
		}

		static string[] Filters = new string[] {".mp3", ".m4a", ".m4b", ".m4p", ".aa"};

		static ArrayList FilterFiles( string[] files )
		{
			ArrayList res = new ArrayList();
			foreach ( string file in files )
			{
				string ext = Path.GetExtension( file ).ToLower();
				if ( 0 <= Array.IndexOf( Filters, ext ) )
					res.Add( file );
			}

			return res;
		}

		static ArrayList GetSoundFilesFromDir( string folder )
		{
			string[] files = Directory.GetFiles( folder );
			ArrayList list = FilterFiles( files );

			string[] folders = Directory.GetDirectories( folder );
			foreach (string sub in folders)
				list.AddRange( GetSoundFilesFromDir( sub ) );

			return list;
		}

		public static void Create_iTunesSD(char drive, string[] soundFiles)
		{
			string iTunesSD = drive+@":\iPod_Control\iTunes\iTunesSD";
			Create_iTunesSD(iTunesSD, soundFiles);
		}
		public static void Create_iTunesSD(string iTunesSD, string[] soundFiles)
		{
			iTunesSD = Path.GetFullPath( iTunesSD );

			string newFile = iTunesSD+".new";

			using (Stream stream = File.Create( newFile ))
			{
				ShuffleWriter writer = new ShuffleWriter(stream);
				writer.Write( soundFiles );
			}

			if (File.Exists(iTunesSD)) File.Delete( iTunesSD );
			File.Move(newFile, iTunesSD);

			string rootFolder = Path.GetDirectoryName( iTunesSD );
			ResetFiles( rootFolder );
		}

		static void ResetFiles( string rootFolder )
		{
			// files to reset/delete
			string[] filesToDelete = new string[] 
			{
				 "iTunesPState"  // playback state
				,"iTunesStats"   // statistics
				,"iTunesShuffle" // shuffle sequence
			};

			foreach (string fileToDelete in filesToDelete)
			{
				string file = Path.Combine( rootFolder, fileToDelete );
				if (File.Exists( file )) 
					File.Delete( file );
			}
		}

		public static DateTime GetLastUpdateTime( char drive )
		{
			string iTunesSD = drive+@":\iPod_Control\iTunes\iTunesSD";
			return File.GetLastWriteTime( iTunesSD );
		}

		static public FILETIME GetFileTime( DateTime time )
		{
			FILETIME res;
			long ft = time.ToFileTime();
			res.dwLowDateTime = (int) ft;
			res.dwHighDateTime= (int) (ft >> 32);
			return res;
		}

		public static string[] Read_iTunesSD( char drive )
		{
			string iTunesSD = drive+@":\iPod_Control\iTunes\iTunesSD";
			return Read_iTunesSD( iTunesSD );
		}

		public static string[] Read_iTunesSD( string iTunesSD )
		{
			try
			{
				string[] files = null;

				if (File.Exists( iTunesSD ))
				using (Stream stream = File.OpenRead( iTunesSD ))
				{
					ShuffleReader reader = new ShuffleReader(stream);
					files = reader.ReadFiles();
				}

				if (null == files)
					files = new string[0];

				return files;
			}
			catch (Exception ex)
			{
				throw new ApplicationException( string.Format(
					"Failed to read file: {0}", iTunesSD ), ex );
			}
		}

		public static bool CompareSoundFiles( string[] files1, string[] files2 )
		{
			if ( files1.Length != files2.Length )
				return false;

			Array.Sort( files1 );
			Array.Sort( files2 );

			for (int i=0; i<files1.Length; i++)
			{
				string file1 = files1[i];
				string file2 = files2[i];

				if ( file1[1] == ':' ) file1 = file1.Remove(0,2);
				if ( file2[1] == ':' ) file2 = file2.Remove(0,2);

				file1 = file1.Replace( '\\', '/' );
				file2 = file2.Replace( '\\', '/' );

				if (0 != string.Compare( file1, file2, true ))
					return false;
			}

			return true;
		}
	}
}
